/**
 * 
 */
package com.wkr.tools;

import java.io.File;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.apache.commons.beanutils.converters.ByteConverter;
import org.apache.commons.beanutils.converters.DoubleConverter;
import org.apache.commons.beanutils.converters.FloatConverter;
import org.apache.commons.beanutils.converters.IntegerConverter;
import org.apache.commons.beanutils.converters.LongConverter;
import org.apache.commons.beanutils.converters.ShortConverter;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;


public class MyUtils {

	/**
	 * 文件上传处理【解析request对象中的文件流对象，并进行文件上传处理】
	 * 
	 * @param request          request对象
	 * @param t                实体类
	 * @param uploadDerictory  上传的文件路径
	 * @param uploadFilePrefix 上文件的前缀
	 * @return 实体类
	 */
	public static <T> T uploadFilesWithRequest(HttpServletRequest request, T t, String uploadDerictory, String uploadFilePrefix) {
		// 注册日期转换器：request参数中的日期类型字符串值则会使用该转换器进行转换为Date类型
		//ConvertUtils.register(new DateTimeConverter4BeanUtils(), Date.class);
		// 将当前上下文初始化给 CommonsMutipartResolver(MutipartResolver接口实现类)
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getServletContext());
		// 检查request发送的form中是否有 enctype="multipart/form-data" 类型的二进制流媒体内容
		if (multipartResolver.isMultipart(request)) {
			// 有文件数据流上传
			// 将request进行转换为MultipartRequest，然后进行处理
			MultipartRequest mr = (MultipartRequest) request;
			// 获取request中的所有的文件标签的name值
			Iterator<String> it = mr.getFileNames();
			// 依次循环request中的所有的文件名，进行文件上传处理
			while (it.hasNext()) {
				// 取出当前的文件名
				String strFileName = it.next();
				// 通过文件名获取文件对象
				MultipartFile multipartFile = mr.getFile(strFileName);
				// 进行文件上传处理
				// 判定是或否有需要处理的文件对象
				if (multipartFile != null) {
					try {
						// 检查含有文件流的part部分进行处理
						// 使用part的ContentType来区分该part是包含文件流控件还是普通控件
						// 获取 MINE类型，普通控件的改属性是 null，文件上传控件的属性不是null
						String partContent = multipartFile.getContentType();
						// 判定文件控件是否上传了文件【判定有没有文件流对象】
						if (partContent != null && !partContent.equals("") && multipartFile.getSize() > 0) {
							// 处理含有文件流空间的part，进行文件上传
							// 准备文件上传的服务器的路径地址【要求是绝对地址】
							String strRealPath = request.getServletContext().getRealPath("/");

							// 规定：默认存储在 static/uploadfiles/
							String strUploadPath = strRealPath;
							// 文件上传时保存的相对路径地址
							String strRelativePath = "static/uploadfiles/" + uploadDerictory;

							// 检测文件上传目录是否已经存在，如果不存在，则创建
							File file = new File(strUploadPath + strRelativePath);
							if (!file.exists()) {
								file.mkdirs();
							}

							// 默认文件后缀为.dat
							String strFileType = ".dat";
							// 获取包含文件后缀信息的上下文的字符描述串
							String strContent = multipartFile.getOriginalFilename();
							// 正则表达式匹配文件后缀
							String strReg = "\\.\\w*";
							// 创建正则表达式类
							Pattern pattern = Pattern.compile(strReg);
							// 进行匹配操作
							Matcher matcher = pattern.matcher(strContent);
							if (matcher.find()) {
								strFileType = matcher.group(0);
							}
							// 组合一个具有随机码的文件名，防止文件重名
							String strNameFileName = uploadFilePrefix + "_" + System.currentTimeMillis() + strFileType;

							// 使用反射将文件存储的相对路径保存到实例类的属性中
							// 上传文件对象

							multipartFile.transferTo(
									new File(strUploadPath + strRelativePath + File.separatorChar + strNameFileName));

							// 将文件的相对路径保存到文件的实体类属性中
							// 获取文件上传控件的name属性
							String strFieldName = multipartFile.getName();
							// 剔除name属性值中的前缀，才是实体类的属性名
							// 因为表单中的 name属性值为 file_属性名
							String paramName = strFieldName.replace("file_", "");
							// 使用反射将表单的value值设置到与之对应的实体类属性中【借助beanutils或者直接使用反射】
							BeanUtils.setProperty(t, paramName, strRelativePath + File.separatorChar + strNameFileName);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}

			}

		}

		return t;
	}
}